home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / GoldED Tools / NextStep / source / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  38.7 KB  |  1,489 lines

  1. /* -----------------------------------------------------------------------------
  2.  
  3.  GoldED API client. ©1995 Dietmar Eilert. All Rights Reserved.
  4.  
  5.  Dice:
  6.  
  7.  dcc main.c cx.a sprintf.a -// -mRR -proto -2.0 -l tmsr.lib -l reqtoolssr.lib -o ram:dock
  8.  
  9.  Note: Compiling this code requires ToolManger includes & ToolManager linker
  10.        libraries. ToolManager is ©1990-1995 Stefan Becker.
  11.  
  12.   ------------------------------------------------------------------------------
  13. */
  14.  
  15. /// "includes"
  16.  
  17. #define Prototype extern
  18.  
  19. #include <exec/exec.h>
  20. #include <ctype.h>
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <dos/dos.h>
  25. #include <dos/rdargs.h>
  26. #include <dos/dostags.h>
  27. #include <intuition/intuition.h>
  28. #include <workbench/startup.h>
  29. #include <rexx/errors.h>
  30. #include <rexx/rxslib.h>
  31. #include <rexx/storage.h>
  32. #include <libraries/reqtools.h>
  33. #include <utility/tagitem.h>
  34. #include <clib/toolmanager_protos.h>
  35. #include <clib/exec_protos.h>
  36. #include <clib/alib_protos.h>
  37. #include <clib/dos_protos.h>
  38. #include <clib/intuition_protos.h>
  39. #include <clib/utility_protos.h>
  40. #include <clib/rexxsyslib_protos.h>
  41. #include <clib/reqtools_protos.h>
  42. #include <clib/commodities_protos.h>
  43. #include "golded:api/include/golded.h"
  44.  
  45. #define SIG_KILL         SIGBREAKF_CTRL_C
  46. #define SIG_HANDSHAKE    SIGF_SINGLE
  47. #define TMET_Hotkey      10
  48. #define TMET_GoldED      11
  49.  
  50. ///
  51. /// "definitions"
  52.  
  53. // ToolManager objects are a combination of action/image/sound:
  54.  
  55. struct Tool {
  56.  
  57.     struct Node     Node;
  58.     APTR            Exec;
  59.     APTR            Icon;
  60.     APTR            Sound;
  61. };
  62.  
  63. // parser array: commands, templates, handlers
  64.  
  65. struct Parser { 
  66.  
  67.     UBYTE          *Command;
  68.     APTR            Server;
  69.     UBYTE          *Template;
  70. };
  71.  
  72. // linked list of all PROG objects (CLI/AREXX/HOTKEY/GOLDED) found in the preset file:
  73.  
  74. struct Event {
  75.  
  76.     struct Node     Node;
  77.     UWORD           Type;
  78.     UBYTE          *Command;
  79.     UBYTE          *Dir;
  80.     UBYTE          *Key;
  81.     UBYTE          *Output;
  82.     BOOL            Hotkey;
  83.     BOOL            Args;
  84.     BOOL            Activate;
  85. };
  86.  
  87. // linked list of all docks found in the preset file:
  88.  
  89. struct Dock {
  90.  
  91.     struct Node     Node;
  92.     struct TagItem *Tags;
  93.     BOOL            Visible;
  94.     UWORD           Elements;
  95. };
  96.  
  97. ///
  98. /// "prototypes"
  99.  
  100. Prototype void   StopServer(struct Task **);
  101. Prototype void   InsertEvent(UBYTE *);
  102. Prototype void   PutIEvents(struct InputEvent *);
  103. Prototype int    main(int, char **);
  104. Prototype UBYTE *xsprintf(UBYTE *, UBYTE *);
  105. Prototype void   AddProg (ULONG *, struct List *);
  106. Prototype void   AddIcon (ULONG *, struct List *);
  107. Prototype void   AddSound(ULONG *, struct List *);
  108. Prototype void   AddTool (ULONG *, struct List *);
  109. Prototype void   AddDock (ULONG *, struct List *);
  110. Prototype void   HandleAPI(struct Task **);
  111. Prototype void   ReadConfig(UBYTE *);
  112. Prototype void   CloseRexxPort(struct MsgPort *, UWORD, BOOL);
  113. Prototype ULONG *SendRexxCommand(UBYTE *, UBYTE *, struct MsgPort *, BOOL, UWORD *, UBYTE *);
  114. Prototype struct Node *SearchName(struct List *, UBYTE *);
  115. Prototype void   FreeRexxCommand(struct RexxMsg *);
  116. Prototype UWORD  CountList(struct List *);
  117. Prototype void   Puts(UBYTE *);
  118. Prototype UBYTE *myprintf(UBYTE *, UBYTE *, ...);
  119. Prototype void   ARexxServer(void);
  120. Prototype void   ShowDocks(struct Dock *);
  121. Prototype void   HideDocks(void);
  122. Prototype void   DoExecute(UBYTE *, BOOL, UBYTE *, UBYTE *, UWORD, WORD);
  123. Prototype UBYTE *stristr(UBYTE *, UBYTE *);
  124. Prototype void   Replace(UBYTE *, UBYTE *, UBYTE *);
  125. Prototype void   CommandDispatch(struct RDArgs *, struct APIMessage *);
  126. Prototype LONG   ModifyDock(ULONG *, struct APIMessage *);
  127.  
  128. Prototype __stkargs struct InputEvent *MyInvertString(UBYTE *, APTR);
  129. Prototype __stkargs void               MyFreeIEvents(struct InputEvent *);
  130.  
  131. ///
  132. /// "globals"
  133.  
  134. UBYTE Version = "$VER: NextStep 1.6 (" __COMMODORE_DATE__ ")";
  135.  
  136. UWORD            ARexxReplies;
  137. struct Library  *ReqToolsBase;
  138. struct Library  *CxBase;
  139. struct Task     *MainTask;
  140. struct List      EventList, DockList;
  141. void            *TMHandle;
  142. UBYTE            Screen[255], Host[255];
  143.  
  144. // parser definitions used to scan preset file
  145.  
  146. struct Parser ConfigParser[] = {
  147.  
  148.     "PROG",  (APTR)AddProg,    "NAME/A,COMMAND/K/A,AREXX/S,CLI/S,HOTKEY/S,WB/S,DIR/K,OUTPUT/K,ARGS/S,KEY/K,GOLDED/S,ACTIVATE/S",
  149.     "SOUND", (APTR)AddSound,   "NAME/A,COMMAND/K/A,PORT/K/A",
  150.     "ICON",  (APTR)AddIcon,    "NAME/A,FILE/A",
  151.     "DTOOL", (APTR)AddTool,    "PROG/K/A,ICON/K,SOUND/K",
  152.     "DOCK",  (APTR)AddDock,    "NAME/A,X/N,Y/N,HORIZONTAL/S,COLUMNS/N,HOTKEY/K,TITLE/K,CENTER/S,POPUP/S,HIDDEN/S,TEXT/S,STICKY/S,FRONTMOST/S,PATTERN/S,VERTICAL/S,LINEAR/S",
  153.      NULL
  154. };
  155.  
  156. // parser definitions used to process commands sent by GoldED (API interface):
  157.  
  158. struct Parser CommandParser[] = {
  159.  
  160.     "DOCK",  (APTR)ModifyDock, "NAME/A,X/N,Y/N,SHOW/S,HIDE/S,TOGGLE/S,HORIZONTAL/S,VERTICAL/S,ROTATE/S,NEWLOOK/S,LINEAR/S",
  161.      NULL
  162. };
  163.  
  164. ///
  165. /// "main"
  166.  
  167. /* ----------------------------------- main ------------------------------------
  168.  
  169.  Start ToolManager, start background server (server performs all dock-related
  170.  actions, e.g. the server will run commands), read config file, call API loop.
  171.  
  172. */
  173.  
  174. int
  175. main(int argc, char **argv)
  176. {
  177.     if (FindPort("DOCKSERVER"))
  178.  
  179.         Puts("NextStep: Can't run dock twice");
  180.  
  181.     else if (CxBase = OpenLibrary("commodities.library", 37)) {
  182.  
  183.         struct RDArgs *rdArgs;
  184.  
  185.         ULONG args[] = { 0, 0 };
  186.  
  187.         MainTask = FindTask(0);
  188.  
  189.         if (rdArgs = ReadArgs("CONFIG/K,HOST/K/A", args, NULL)) {
  190.  
  191.             UWORD  try;
  192.  
  193.             for (try = 20; !(TMHandle = AllocTMHandle()) && try; try--)
  194.                 Delay(10);
  195.  
  196.             if (TMHandle) {
  197.  
  198.                 struct Task *server;
  199.  
  200.                 if (server = (struct Task *)CreateNewProcTags(NP_Entry, ARexxServer, NP_Name, "DOCKSERVER", NP_Priority, 1, TAG_DONE)) {
  201.  
  202.                     NewList(&DockList );
  203.                     NewList(&EventList);
  204.  
  205.                     strcpy(Host, (UBYTE *)args[1]);
  206.  
  207.                     ReadConfig(args[0] ? (char *)args[0] : "progdir:dock.prefs");
  208.  
  209.                     if (DockList.lh_Head->ln_Succ)
  210.                         HandleAPI(&server);
  211.  
  212.                     FreeTMHandle(TMHandle);
  213.  
  214.                     StopServer(&server);
  215.                 }
  216.             }
  217.             else
  218.                 Puts("got no ToolManager handle ?!");
  219.  
  220.             FreeArgs(rdArgs);
  221.         }
  222.         else
  223.             Puts("syntax error");
  224.  
  225.         CloseLibrary(CxBase);
  226.     }
  227.  
  228.     exit(0);
  229. }
  230.  
  231. /* ---------------------------------- wbmain -----------------------------------
  232.  
  233.  Workbench entry point; exit gracefully
  234.  
  235. */
  236.  
  237. int
  238. wbmain(struct WBStartup *startup)
  239. {
  240.     if (ReqToolsBase = OpenLibrary("reqtools.library", 37)) {
  241.  
  242.         rtEZRequestTags("No executable - to be used as GoldED API client", "OK", NULL, NULL, TAG_DONE);
  243.  
  244.         CloseLibrary(ReqToolsBase);
  245.     }
  246.  
  247.     exit(0);
  248. }
  249.  
  250.  
  251. ///
  252. /// "read config"
  253.  
  254. /* -------------------------------- ReadConfig ---------------------------------
  255.  
  256.  Read preset file. Build linked list of  dock  definitions  (DockList).  PROG
  257.  definitions  (AREXX/CLI/HOTKEY/GOLDED)  are  appended  to the EventList; the
  258.  contents of the EventList are examined if ToolManger tells us  that  a  dock
  259.  icon  has  been  activated  by the user. DTOOL definitions (command + icon +
  260.  sound) are appended to the <toolList>. The <tooList> is appended to the next
  261.  dock created by a DOCK line.
  262.  
  263. */
  264.  
  265. void
  266. ReadConfig(prefs)
  267.  
  268. UBYTE *prefs;
  269. {
  270.     BPTR config;
  271.  
  272.     if (config = Open(prefs, MODE_OLDFILE)) {
  273.  
  274.         struct RDArgs *rdArgs;
  275.  
  276.         struct List toolList;
  277.  
  278.         NewList(&toolList);
  279.  
  280.         if (rdArgs = AllocDosObject(DOS_RDARGS, NULL)) {
  281.  
  282.             static UBYTE buffer[256];
  283.  
  284.             while (FGets(config, buffer, 255)) {
  285.  
  286.                 UBYTE *cmd;
  287.  
  288.                 for (strcat(buffer, "\12"), cmd = buffer; *cmd && (*cmd != ';'); ++cmd) {
  289.  
  290.                     if ((*cmd != ' ') && (*cmd != 10)) {
  291.  
  292.                         ULONG n, argArray[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  293.  
  294.                         struct RDArgs *args;
  295.  
  296.                         for (n = 0; ConfigParser[n].Command; ++n) {
  297.  
  298.                             if (!memcmp(cmd, ConfigParser[n].Command, strlen(ConfigParser[n].Command))) {
  299.  
  300.                                 cmd += strlen(ConfigParser[n].Command);
  301.  
  302.                                 rdArgs->RDA_Source.CS_Buffer = cmd;
  303.                                 rdArgs->RDA_Source.CS_Length = strlen(cmd);
  304.                                 rdArgs->RDA_Source.CS_CurChr = 0;
  305.                                 rdArgs->RDA_DAList           = NULL;
  306.                                 rdArgs->RDA_Buffer           = NULL;
  307.  
  308.                                 if (args = ReadArgs(ConfigParser[n].Template, argArray, rdArgs)) {
  309.  
  310.                                     (*((void (*)(ULONG *, struct List *))ConfigParser[n].Server))(argArray, &toolList);
  311.  
  312.                                     FreeArgs(args);
  313.                                 }
  314.                                 else {
  315.  
  316.                                     PrintFault(IoErr(), "syntax error");
  317.                                     Puts(buffer);
  318.                                 }
  319.                             }
  320.                         }
  321.  
  322.                         break;
  323.                     }
  324.                 }
  325.             }
  326.  
  327.             FreeDosObject(DOS_RDARGS, rdArgs);
  328.         }
  329.  
  330.         Close(config);
  331.     }
  332.     else
  333.         Puts("dock preset file missing");
  334. }
  335.  
  336. /* ---------------------------------- AddProg ----------------------------------
  337.  
  338.  Add a command object (exec/WB/ARexx). The command definition is  added  to  our
  339.  internal EventList only. An ARexx object is added to ToolManagers pool, telling
  340.  ToolManager to send us the object's name upon activation: Events are  performed
  341.  by  us  (i.e.  the  background  task),  not  by  ToolManager. This gives us the
  342.  opportunity to change command strings before execution (e.g. in order to insert
  343.  GoldED's  current screen name). Event definitions are added to the <EventList>;
  344.  we are going to scan this list if we recieve ARexx messages by  ToolManager  to
  345.  determine approbiate action.
  346.  
  347.  template: NAME/A,COMMAND/K/A,AREXX/S,CLI/S,HOTKEY/S,WB/S,DIR/K,OUTPUT/K,ARGS/S,KEY/K,GOLDED/S,ACTIVATE/S,SHANGHAI/N",
  348.  
  349. */
  350.  
  351. void
  352. AddProg(args, toolList)
  353.  
  354. ULONG       *args;
  355. struct List *toolList;
  356. {
  357.     struct Event *event;
  358.  
  359.     if (event = malloc(sizeof(struct Event))) {
  360.  
  361.         UBYTE *name = strdup((UBYTE *)args[0]);
  362.  
  363.         struct TagItem execTags[] = {
  364.  
  365.             TMOP_ExecType,  TMET_ARexx,
  366.             TMOP_Command,   xsprintf("'address DOCKSERVER; \42%s\42'", name),
  367.             TAG_DONE
  368.         };
  369.  
  370.         event->Node.ln_Name = strdup((UBYTE *)args[0]);
  371.         event->Command      = strdup((UBYTE *)args[1]);
  372.         event->Dir          = args[6]  ? strdup((UBYTE *)args[6]) : NULL;
  373.         event->Key          = args[9]  ? strdup((UBYTE *)args[9]) : NULL;
  374.         event->Output       = args[7]  ? strdup((UBYTE *)args[7]) : NULL;
  375.         event->Hotkey       = args[4];
  376.         event->Args         = args[8];
  377.         event->Activate     = args[11];
  378.         event->Type         = TMET_CLI;
  379.  
  380.         if (args[2])                                 // AREXX/S
  381.             event->Type = TMET_ARexx;
  382.  
  383.         if (args[5])                                 // WB/S
  384.             event->Type = TMET_WB;
  385.  
  386.         if (args[4])                                 // HOTKEY/S
  387.             event->Type = TMET_Hotkey;
  388.  
  389.         if (args[10])
  390.             event->Type = TMET_GoldED;               // GOLDED/S
  391.  
  392.         AddTail(&EventList, &event->Node);
  393.  
  394.         CreateTMObjectTagList(TMHandle, name, TMOBJTYPE_EXEC, execTags);
  395.     }
  396. }
  397.  
  398. /* ---------------------------------- AddIcon ----------------------------------
  399.  
  400.  Add icon object to ToolManager's pool
  401.  
  402.  template: NAME/A,FILE/A
  403.  
  404. */
  405.  
  406. void
  407. AddIcon(args, toolList)
  408.  
  409. ULONG       *args;
  410. struct List *toolList;
  411. {
  412.     struct TagItem iconTags[] = { 
  413.  
  414.         TMOP_File,  strdup((UBYTE *)args[1]),
  415.         TMOP_Data,  NULL,
  416.         TAG_DONE 
  417.     };
  418.  
  419.     CreateTMObjectTagList(TMHandle, strdup((UBYTE *)args[0]), TMOBJTYPE_IMAGE, iconTags);
  420. }
  421.  
  422.  
  423. /* --------------------------------- AddSound ----------------------------------
  424.  
  425.  Add a sound object to ToolManagers pool
  426.  
  427.  template: NAME/A,COMMAND/K/A,PORT/K/A
  428.  
  429. */
  430.  
  431. void
  432. AddSound(args, toolList)
  433.  
  434. ULONG       *args;
  435. struct List *toolList;
  436. {
  437.     struct TagItem soundTags[] = {
  438.  
  439.         TMOP_Command, strdup((UBYTE *)args[1]),
  440.         TMOP_Port,    strdup((UBYTE *)args[2]),
  441.         TAG_DONE 
  442.     };
  443.  
  444.     CreateTMObjectTagList(TMHandle, strdup((UBYTE *)args[0]), TMOBJTYPE_SOUND, soundTags);
  445. }
  446.  
  447. /* ---------------------------------- AddTool ----------------------------------
  448.  
  449.  Add a tool object (i.e. combination of command, icon, sound) to the list of
  450.  tool objects. This list is a temporary list only; the list is appended to the
  451.  next dock created by a DOCK line found in the preset file.
  452.  
  453.  template: PROG/K/A,ICON/K,SOUND/K
  454.  
  455. */
  456.  
  457. void
  458. AddTool(args, toolList)
  459.  
  460. ULONG       *args;
  461. struct List *toolList;
  462. {
  463.     struct Tool *tool;
  464.  
  465.     if (tool = malloc(sizeof(struct Tool))) {
  466.  
  467.         tool->Exec  = args[0] ? strdup((UBYTE *)args[0]) : NULL;
  468.         tool->Icon  = args[1] ? strdup((UBYTE *)args[1]) : NULL;
  469.         tool->Sound = args[2] ? strdup((UBYTE *)args[2]) : NULL;
  470.  
  471.         AddTail(toolList, &tool->Node);
  472.     }
  473. }
  474.  
  475. /* ---------------------------------- AddDock ----------------------------------
  476.  
  477.  Add a dock description to the list  of  docks.  This  function  won't  actually
  478.  create  a  dock on the screen. Instead, it will create a ready-to-use tag list.
  479.  Passing this list to the ToolManager library (done by ShowDocks()) will  create
  480.  the dock.
  481.  
  482.  template: NAME/A,X/N,Y/N,HORIZONTAL/S,COLUMNS/N,HOTKEY/K,TITLE/K,CENTER/S,POPUP/S,HIDDEN/S,TEXT/S,STICKY/S,FRONTMOST/S,PATTERN/S,VERTICAL/S,LINEAR/S
  483.  
  484. */
  485.  
  486. void
  487. AddDock(args, toolList)
  488.  
  489. ULONG       *args;
  490. struct List *toolList;
  491. {
  492.     UWORD entries;
  493.  
  494.     if (entries = CountList(toolList)) {
  495.  
  496.         struct Dock *dock;
  497.  
  498.         if (dock = malloc(sizeof(struct Dock))) {
  499.  
  500.             if (dock->Tags = (struct TagItem *)calloc((entries + 14) * sizeof(struct TagItem), 1)) {
  501.  
  502.                 struct Node *tool;
  503.                 UWORD  n;
  504.  
  505.                 dock->Tags[0].ti_Tag   = TMOP_PubScreen;
  506.  
  507.                 dock->Tags[1].ti_Tag   = TMOP_LeftEdge;
  508.                 dock->Tags[1].ti_Data  = args[1] ? *(ULONG *)args[1] : ~0;
  509.  
  510.                 dock->Tags[2].ti_Tag   = TMOP_TopEdge;
  511.                 dock->Tags[2].ti_Data  = args[2] ? *(ULONG *)args[2] : ~0;
  512.  
  513.                 dock->Tags[3].ti_Tag   = TMOP_Activated;
  514.                 dock->Tags[3].ti_Data  = !args[9];
  515.  
  516.                 dock->Tags[4].ti_Tag   = TMOP_Centered;
  517.                 dock->Tags[4].ti_Data  = args[7];
  518.  
  519.                 dock->Tags[5].ti_Tag   = TMOP_Columns;
  520.                 dock->Tags[5].ti_Data  = args[4] ? (*(ULONG *)args[4]) : (args[15] ? (args[14] ? 1 : entries) : 0);
  521.  
  522.                 dock->Tags[6].ti_Tag   = TMOP_Vertical;
  523.                 dock->Tags[6].ti_Data  = !args[14];
  524.  
  525.                 dock->Tags[7].ti_Tag   = TMOP_HotKey;
  526.                 dock->Tags[7].ti_Data  = args[5] ? strdup((UBYTE *)args[5]) : NULL;
  527.  
  528.                 dock->Tags[8].ti_Tag   = TMOP_Title;
  529.                 dock->Tags[8].ti_Data  = args[6] ? strdup((UBYTE *)args[6]) : NULL;                                        // TITLE/K
  530.  
  531.                 dock->Tags[9].ti_Tag   = TMOP_PopUp;
  532.                 dock->Tags[9].ti_Data  = args[8];                                        // TITLE/K
  533.  
  534.                 dock->Tags[10].ti_Tag  = TMOP_Text;
  535.                 dock->Tags[10].ti_Data = args[10];                                        // TITLE/K
  536.  
  537.                 dock->Tags[11].ti_Tag  = TMOP_FrontMost;
  538.                 dock->Tags[11].ti_Data = args[12];                                        // TITLE/K
  539.  
  540.                 dock->Tags[12].ti_Tag  = TMOP_Pattern;
  541.                 dock->Tags[12].ti_Data = args[13];                                        // TITLE/K
  542.  
  543.                 // add the tool description tags:
  544.  
  545.                 for (n = 13, tool = toolList->lh_Head; tool->ln_Succ; ++n, tool = tool->ln_Succ) {
  546.  
  547.                     dock->Tags[n].ti_Tag  = TMOP_Tool;
  548.                     dock->Tags[n].ti_Data = &((struct Tool *)tool)->Exec;
  549.                 }
  550.  
  551.                 dock->Tags[n].ti_Tag  = TAG_DONE;
  552.                 dock->Tags[n].ti_Data = NULL;
  553.  
  554.                 dock->Visible  = FALSE;
  555.                 dock->Elements = entries;
  556.  
  557.                 dock->Node.ln_Name = strdup((UBYTE *)args[0]);
  558.  
  559.                 AddTail(&DockList, &dock->Node);
  560.             }
  561.         }
  562.     }
  563.     else
  564.         Puts("error: dock empty");
  565.  
  566.     NewList(toolList);
  567. }
  568.  
  569. ///
  570. /// "API management"
  571.  
  572. /* --------------------------------- HandleAPI ---------------------------------
  573.  
  574.  Register with GoldED & handle incoming API messages.
  575.  
  576. */
  577.  
  578. void
  579. HandleAPI(server)
  580.  
  581. struct Task **server;
  582. {
  583.     struct MsgPort *rexxPort, *apiPort;
  584.  
  585.     if (rexxPort = CreateMsgPort()) {
  586.  
  587.         if (apiPort = CreateMsgPort()) {
  588.  
  589.             struct RDArgs *rdArgs;
  590.  
  591.             if (rdArgs = AllocDosObject(DOS_RDARGS, NULL)) {
  592.  
  593.                 UBYTE  command[255];
  594.                 ULONG *result;
  595.  
  596.                 myprintf(command, "API PORT=%ld CLASS=%ld", apiPort, API_CLASS_ROOT | API_CLASS_SCREEN | API_CLASS_REXX);
  597.  
  598.                 if ((result = SendRexxCommand(Host, command, rexxPort, FALSE, NULL, NULL)) && (*result == RC_OK)) {
  599.  
  600.                     do {
  601.  
  602.                         struct APIMessage *apiMsg, *nextMsg;
  603.  
  604.                         while (!(apiMsg = (struct APIMessage *)GetMsg(apiPort)))
  605.  
  606.                             WaitPort(apiPort);
  607.  
  608.                         do {
  609.  
  610.                             for (nextMsg = apiMsg; nextMsg; nextMsg = nextMsg->api_Next) {
  611.  
  612.                                 if (nextMsg->api_State == API_STATE_NOTIFY) {
  613.  
  614.                                     switch (nextMsg->api_Class) {
  615.  
  616.                                         case API_CLASS_ROOT:
  617.  
  618.                                             switch (nextMsg->api_Action) {
  619.  
  620.                                                 case API_ACTION_DIE:
  621.  
  622.                                                     HideDocks();
  623.  
  624.                                                     StopServer(server);
  625.  
  626.                                                     server = NULL;
  627.  
  628.                                                     break;
  629.  
  630.                                                 case API_ACTION_INTRODUCE:
  631.  
  632.                                                     static struct TagItem tags[] = {
  633.  
  634.                                                         API_Client_Name,      "NeXTStep",
  635.                                                         API_Client_Copyright, "©1995 Dietmar Eilert",
  636.                                                         API_Client_Purpose,   "Dock Management System",
  637.                                                         API_Client_Template,  "DOCK NAME/A,X/N,Y/N,SHOW/S,HIDE/S,TOGGLE/S,HORIZONTAL/S,VERTICAL/S,ROTATE/S,NEWLOOK/S,LINEAR/S",
  638.                                                         TAG_DONE
  639.                                                     };
  640.  
  641.                                                     nextMsg->api_Data = tags;
  642.                                                     break;
  643.  
  644.                                                 default:
  645.  
  646.                                                     nextMsg->api_Error = API_ERROR_UNKNOWN;
  647.                                             }
  648.  
  649.                                             break;
  650.  
  651.                                         case API_CLASS_REXX:
  652.  
  653.                                             switch (nextMsg->api_Action) {
  654.  
  655.                                                 case API_ACTION_COMMAND:
  656.  
  657.                                                     CommandDispatch(rdArgs, nextMsg);
  658.                                                     break;
  659.  
  660.                                                 default:
  661.  
  662.                                                     nextMsg->api_Error = API_ERROR_UNKNOWN;
  663.                                             }
  664.                                             break;
  665.  
  666.                                         case API_CLASS_SCREEN:
  667.  
  668.                                             switch (nextMsg->api_Action) {
  669.  
  670.                                                 case API_ACTION_HIDE:
  671.  
  672.                                                     HideDocks();
  673.                                                     break;
  674.  
  675.                                                 case API_ACTION_SHOW:
  676.  
  677.                                                     strcpy(Screen, nextMsg->api_Global->F_ScrnName);
  678.  
  679.                                                     ShowDocks(NULL);
  680.                                                     break;
  681.  
  682.                                                 default:
  683.  
  684.                                                     nextMsg->api_Error = API_ERROR_UNKNOWN;
  685.                                             }
  686.                                             break;
  687.  
  688.                                         default:
  689.  
  690.                                             nextMsg->api_Error = API_ERROR_UNKNOWN;
  691.                                     }
  692.                                 }
  693.                             }
  694.  
  695.                             ReplyMsg((struct Message *)apiMsg);
  696.  
  697.                         } while (apiMsg = (struct APIMessage *)GetMsg(apiPort));
  698.  
  699.                     } while (server);
  700.                 }
  701.  
  702.                 FreeDosObject(DOS_RDARGS, rdArgs);
  703.             }
  704.  
  705.             DeleteMsgPort(apiPort);
  706.         }
  707.  
  708.         DeleteMsgPort(rexxPort);
  709.     }
  710. }
  711.  
  712. ///
  713. /// "command dispatcher"
  714.  
  715. /* ------------------------------ CommandDispatch ------------------------------
  716.  
  717.  Dispatch commands sent by GoldED via the API interface. Commands are uppercase.
  718.  
  719. */
  720.  
  721. void
  722. CommandDispatch(rdArgs, apiMsg)
  723.  
  724. struct RDArgs     *rdArgs;
  725. struct APIMessage *apiMsg;
  726. {
  727.     struct APIRexxNotify *notify = (struct APIRexxNotify *)apiMsg->api_Data;
  728.  
  729.     UWORD n;
  730.  
  731.     for (n = 0; CommandParser[n].Command; ++n) {
  732.  
  733.         if (memcmp(notify->arn_Command, CommandParser[n].Command, strlen(CommandParser[n].Command)) == NULL) {
  734.  
  735.             static UBYTE buffer[1024];
  736.             
  737.             UBYTE *arguments = buffer + strlen(CommandParser[n].Command);
  738.  
  739.             strcpy(buffer, notify->arn_Command);
  740.             strcat(buffer, "\12");
  741.  
  742.             rdArgs->RDA_Source.CS_Buffer = arguments;
  743.             rdArgs->RDA_Source.CS_Length = strlen(arguments);
  744.             rdArgs->RDA_Source.CS_CurChr = 0;
  745.             rdArgs->RDA_DAList           = NULL;
  746.             rdArgs->RDA_Buffer           = NULL;
  747.  
  748.             if (CommandParser[n].Template) {
  749.  
  750.                 ULONG argArray[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  751.  
  752.                 if (ReadArgs(CommandParser[n].Template, argArray, rdArgs)) {
  753.  
  754.                     notify->arn_RC = (*(LONG (*)(ULONG *, struct APIMessage *))CommandParser[n].Server)(argArray, apiMsg);
  755.  
  756.                     FreeArgs(rdArgs);
  757.                 }
  758.                 else {
  759.  
  760.                     static char errorText[81];
  761.  
  762.                     Fault(IoErr(), "IoErr()", errorText, 80);
  763.  
  764.                     notify->arn_RC           = RC_WARN;
  765.                     notify->arn_CommandError = errorText;
  766.                 }
  767.             }
  768.             else
  769.                 notify->arn_RC = (*(LONG (*)(ULONG *, struct APIMessage *))CommandParser[n].Server)(NULL, apiMsg);
  770.  
  771.             apiMsg->api_State = API_STATE_CONSUMED;
  772.         }
  773.     }
  774. }
  775.  
  776. /* -------------------------------- ModifyDock ---------------------------------
  777.  
  778.  Modify look of a dock
  779.  
  780.  template: NAME/A,X/N,Y/N,SHOW/S,HIDE/S,TOGGLE/S,HORIZONTAL/S,VERTICAL/S,ROTATE/S,NEWLOOK/S,LINEAR/S
  781.  
  782. */
  783.  
  784. LONG
  785. ModifyDock(args, apiMsg)
  786.  
  787. ULONG  *args;
  788. struct APIMessage *apiMsg;
  789. {
  790.     struct Dock *dock;
  791.  
  792.     if (dock = SearchName(&DockList, (UBYTE *)args[0])) {
  793.  
  794.         struct TagItem *tag;
  795.         BOOL            visible;
  796.  
  797.         if (visible = dock->Visible)
  798.             DeleteTMObject(TMHandle, dock->Node.ln_Name);
  799.  
  800.         dock->Visible = FALSE;
  801.  
  802.         if (args[1])                                 // X/N
  803.  
  804.             FindTagItem(TMOP_LeftEdge, dock->Tags)->ti_Data = *(ULONG *)args[1];
  805.  
  806.         if (args[2])                                 // Y/N
  807.  
  808.             FindTagItem(TMOP_TopEdge, dock->Tags)->ti_Data = *(ULONG *)args[2];
  809.  
  810.         tag = FindTagItem(TMOP_Vertical, dock->Tags);
  811.  
  812.         if (args[6])                                 // HORIZONTAL/S
  813.             tag->ti_Data = TRUE;
  814.  
  815.         if (args[7])                                 // VERTICAL/S
  816.             tag->ti_Data = FALSE;
  817.  
  818.         if (args[8])                                 // ROTATE/S
  819.             tag->ti_Data = !tag->ti_Data;
  820.  
  821.         if (args[10])                                // LINEAR/S
  822.  
  823.             FindTagItem(TMOP_Columns, dock->Tags)->ti_Data = (tag->ti_Data) ? dock->Elements : 1;
  824.  
  825.         tag = FindTagItem(TMOP_Text, dock->Tags);
  826.  
  827.         if (args[9])                                 // NEWLOOK/S
  828.             tag->ti_Data = !tag->ti_Data;
  829.  
  830.         if (args[3])                                 // SHOW/S
  831.             visible = TRUE;
  832.  
  833.         if (args[4])                                 // HIDE/S
  834.             visible = FALSE;
  835.  
  836.         if (args[5])                                 // TOGGLE/S
  837.             visible = !visible;
  838.  
  839.         if (visible)
  840.             ShowDocks(dock);
  841.     }
  842.     else
  843.         Puts("Unknow dock");
  844.  
  845.     return(RC_OK);
  846. }
  847.  
  848. ///
  849. /// "dock handling"
  850.  
  851. /* --------------------------------- ShowDocks ---------------------------------
  852.  
  853.  Show specified (hidden) dock or all hidden docks if <dock> is FALSE.
  854.  
  855. */
  856.  
  857. void
  858. ShowDocks(showDock)
  859.  
  860. struct Dock *showDock;
  861. {
  862.     struct Screen *scr;
  863.  
  864.     if (scr = LockPubScreen(Screen)) {
  865.  
  866.         struct Dock *dock;
  867.  
  868.         for (dock = (struct Dock *)DockList.lh_Head; dock->Node.ln_Succ; dock = (struct Dock *)dock->Node.ln_Succ) {
  869.  
  870.             if (!dock->Visible) {
  871.  
  872.                 if ((dock == showDock) || (showDock == NULL)) {
  873.  
  874.                     struct TagItem *tag;
  875.  
  876.                     FindTagItem(TMOP_PubScreen, dock->Tags)->ti_Data = Screen;
  877.  
  878.                     if ((tag = FindTagItem(TMOP_LeftEdge, dock->Tags))->ti_Data == ~0)
  879.                         tag->ti_Data = scr->Width;
  880.  
  881.                     if ((tag = FindTagItem(TMOP_TopEdge, dock->Tags))->ti_Data == ~0)
  882.                         tag->ti_Data = scr->BarHeight + ((scr->BitMap.Depth == 1) ? 2 : 1);
  883.  
  884.                     if (CreateTMObjectTagList(TMHandle, dock->Node.ln_Name, TMOBJTYPE_DOCK, dock->Tags))
  885.                         dock->Visible = TRUE;
  886.                     else
  887.                         Puts("Couldn't create dock object");
  888.                 }
  889.             }
  890.         }
  891.  
  892.         UnlockPubScreen(NULL, scr);
  893.     }
  894. }
  895.  
  896. /* --------------------------------- HideDocks ---------------------------------
  897.  
  898.  Hide all open docks
  899.  
  900. */
  901.  
  902. void
  903. HideDocks()
  904. {
  905.     struct Dock *dock;
  906.  
  907.     for (dock = (struct Dock *)DockList.lh_Head; dock->Node.ln_Succ; dock = (struct Dock *)dock->Node.ln_Succ) {
  908.  
  909.         if (dock->Visible) {
  910.  
  911.             DeleteTMObject(TMHandle, dock->Node.ln_Name);
  912.  
  913.             dock->Visible = FALSE;
  914.         }
  915.     }
  916. }
  917.  
  918.  
  919. ///
  920. /// "misc"
  921.  
  922.  
  923. /* --------------------------------- StopServer --------------------------------
  924.  
  925.  Stop server task
  926.  
  927. */
  928.  
  929. void
  930. StopServer(server)
  931.  
  932. struct Task **server;
  933. {
  934.     if (*server) {
  935.  
  936.         SetSignal(0, SIG_HANDSHAKE);
  937.  
  938.         Signal(*server, SIG_KILL);
  939.  
  940.         Wait(SIG_HANDSHAKE);
  941.  
  942.         *server = NULL;
  943.     }
  944. }
  945.  
  946.  
  947. /* -------------------------------- PutIEvents ---------------------------------
  948.  
  949.  Add keyboard events to global stream of input events. Works  recursively  to
  950.  invert   the  given  linked  list  of  events  (which  is  inverted  due  to
  951.  InvertString). Restores the links after usage  to  support  a  FreeIEvents()
  952.  call later on.
  953.  
  954. */
  955.  
  956. void
  957. PutIEvents(inputEvent)
  958.  
  959. struct InputEvent *inputEvent;
  960. {
  961.     struct InputEvent *next;
  962.  
  963.     if (next = inputEvent->ie_NextEvent)
  964.         PutIEvents(next);
  965.  
  966.     inputEvent->ie_NextEvent = NULL;
  967.  
  968.     AddIEvents(inputEvent);
  969.  
  970.     inputEvent->ie_NextEvent = next;
  971. }
  972.  
  973. /* ---------------------------------- InsertEvent ------------------------------
  974.  
  975.  Insert string into input event loop. String is interpreted. Return FALSE on
  976.  failure (interpretation error).
  977.  
  978. */
  979.  
  980. void
  981. InsertEvent(string)
  982.  
  983. UBYTE *string;
  984. {
  985.     struct InputEvent *inputEvent;
  986.  
  987.     if (inputEvent = MyInvertString(string, NULL)) {
  988.  
  989.         PutIEvents   (inputEvent);
  990.         MyFreeIEvents(inputEvent);
  991.     }
  992. }
  993.  
  994.  
  995. /* ---------------------------------- stristr ----------------------------------
  996.  
  997.  strstr replacement: case insensitive (recursive)
  998.  
  999. */
  1000.  
  1001. UBYTE *
  1002. stristr(buffer, pattern)
  1003.  
  1004. UBYTE *buffer, *pattern;
  1005. {
  1006.     if (*pattern) {
  1007.  
  1008.         while (*buffer) {
  1009.  
  1010.             if (toupper(*buffer) == *pattern)
  1011.                 if (stristr(buffer + 1, pattern + 1))
  1012.                     return(buffer);
  1013.  
  1014.             ++buffer;
  1015.         }
  1016.  
  1017.         return(NULL);
  1018.     }
  1019.     else
  1020.         return(buffer);
  1021. }
  1022.  
  1023. /* ---------------------------------- Replace ----------------------------------
  1024.  
  1025.  Replace given <pattern> within <buffer> by <new> (case insensitive)
  1026.  
  1027. */
  1028.  
  1029. void
  1030. Replace(buffer, pattern, new)
  1031.  
  1032. UBYTE *buffer, *pattern, *new;
  1033. {
  1034.     UWORD newLen;
  1035.     
  1036.     for (newLen = strlen(new); buffer = stristr(buffer, pattern); buffer += newLen) {
  1037.  
  1038.         WORD diffLen = newLen - strlen(pattern);
  1039.  
  1040.         if (diffLen > 0)
  1041.             movmem(buffer, buffer + diffLen, strlen(buffer) + 1);
  1042.  
  1043.         if (diffLen < 0)
  1044.             strcpy(buffer, buffer - diffLen);
  1045.  
  1046.         movmem(new, buffer, newLen);
  1047.     }
  1048. }
  1049.  
  1050.  
  1051. /* -------------------------------- SearchName ---------------------------------
  1052.  
  1053.  Search for named node; case insensitive FindName() replacement
  1054.  
  1055. */
  1056.  
  1057. struct Node *
  1058. SearchName(list, name)
  1059.  
  1060. struct List *list;
  1061. UBYTE       *name;
  1062. {
  1063.     struct Node *node;
  1064.  
  1065.     if (node = FindName(list, name))
  1066.         return(node);
  1067.  
  1068.     for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ)
  1069.         if (node->ln_Name && (stricmp(name, node->ln_Name) == 0))
  1070.             return(node);
  1071.  
  1072.     return(NULL);
  1073. }
  1074.  
  1075. /* ----------------------------------- Puts ------------------------------------
  1076.  
  1077.  puts() replacement; saves another 2K ;-)
  1078.  
  1079. */
  1080.  
  1081. void
  1082. Puts(text)
  1083.  
  1084. UBYTE *text;
  1085. {
  1086.     Write(Output(), text, strlen(text));
  1087.     Write(Output(), "\n", 1);
  1088. }
  1089.  
  1090.  
  1091. /* ---------------------------------- CountList --------------------------------
  1092.  
  1093.  Count nodes of a list
  1094.  
  1095. */
  1096.  
  1097. UWORD
  1098. CountList(list)
  1099.  
  1100. struct List *list;
  1101. {
  1102.     UWORD  count;
  1103.     struct Node *nextNode;
  1104.  
  1105.     for (count = 0, nextNode = list->lh_Head; nextNode->ln_Succ; nextNode = nextNode->ln_Succ)
  1106.         count++;
  1107.  
  1108.     return(count);
  1109. }
  1110.  
  1111.  
  1112. /* --------------------------------- xsprintf ----------------------------------
  1113.  
  1114.  sprintf frontend (malloc buffer); limited to string insertion into string
  1115.  
  1116. */
  1117.  
  1118. UBYTE *
  1119. xsprintf(mask, var)
  1120.  
  1121. UBYTE *mask, *var;
  1122. {
  1123.     char *buffer;
  1124.  
  1125.     if (buffer = malloc(strlen(mask) + strlen(var)))
  1126.         myprintf(buffer, mask, var);
  1127.  
  1128.     return(buffer);
  1129. }
  1130.  
  1131. ///
  1132. /// "ARexx"
  1133.  
  1134. /* ---------------------------------- SendRexxCommand -------------------------
  1135.  
  1136.  Send ARexx message & wait for answer. Don't wait for reply  in  asynchronous
  1137.  mode.  In  synchronous mode: return pointer to result or NULL. Result string
  1138.  is written to <buffer> if <buffer> is valid. In  asynchronous  mode:  return
  1139.  TRUE (message sent; increase <counter>) or NULL.
  1140.  
  1141. */
  1142.  
  1143. ULONG *
  1144. SendRexxCommand(port, cmd, replyPort, async, counter, buffer)
  1145.  
  1146. UBYTE *cmd, *port, *buffer;
  1147. UWORD *counter;
  1148. BOOL   async;
  1149. struct MsgPort *replyPort;
  1150. {
  1151.     struct MsgPort *rexxport;
  1152.  
  1153.     Forbid();
  1154.  
  1155.     if (rexxport = FindPort(port)) {
  1156.  
  1157.         struct RexxMsg *rexxMsg;
  1158.  
  1159.         if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {
  1160.  
  1161.             if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {
  1162.  
  1163.                 static ULONG result;
  1164.  
  1165.                 struct RexxMsg *answer;
  1166.  
  1167.                 rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;
  1168.  
  1169.                 PutMsg(rexxport, &rexxMsg->rm_Node);
  1170.  
  1171.                 Permit();
  1172.  
  1173.                 if (counter)
  1174.                     ++*counter;
  1175.  
  1176.                 if (async)
  1177.                     return(TRUE);
  1178.  
  1179.                 do {
  1180.  
  1181.                     WaitPort(replyPort);
  1182.  
  1183.                     if (answer = (struct RexxMsg *)GetMsg(replyPort)) {
  1184.  
  1185.                         if (answer->rm_Node.mn_Node.ln_Type == NT_REPLYMSG) {
  1186.  
  1187.                             if (counter)
  1188.                                 --*counter;
  1189.  
  1190.                             if (answer == rexxMsg) {
  1191.  
  1192.                                 if ((result = answer->rm_Result1) == RC_OK) {
  1193.  
  1194.                                     if (answer->rm_Result2 && buffer)
  1195.                                         strcpy(buffer, (char *)answer->rm_Result2);
  1196.                                 }
  1197.                             }
  1198.  
  1199.                             FreeRexxCommand(answer);
  1200.                         }
  1201.                         else {
  1202.  
  1203.                             answer->rm_Result1 = RC_FATAL;
  1204.  
  1205.                             ReplyMsg((struct Message *)answer);
  1206.                         }
  1207.                     }
  1208.  
  1209.                 } while (answer != rexxMsg);
  1210.  
  1211.                 return(&result);
  1212.             }
  1213.         }
  1214.     }
  1215.  
  1216.     Permit();
  1217.  
  1218.     return(NULL);
  1219. }
  1220.  
  1221. /* ------------------------------- CloseRexxPort -------------------------------
  1222.  
  1223.  Close an ARexx  port.  Wait  until  all  outstanding  (i.e.  sent)  messages
  1224.  (<missing>)  have  been  replied.  Remove  port from list of public ports if
  1225.  <removePort> is TRUE.
  1226.  
  1227. */
  1228.  
  1229. void
  1230. CloseRexxPort(port, missing, removePort)
  1231.  
  1232. struct MsgPort *port;
  1233. UWORD  missing;
  1234. BOOL   removePort;
  1235. {
  1236.     if (removePort)
  1237.         RemPort(port);
  1238.  
  1239.     Forbid();
  1240.  
  1241.     while (missing) {
  1242.  
  1243.         struct RexxMsg *rexxMsg;
  1244.  
  1245.         Wait(1L<<port->mp_SigBit);
  1246.  
  1247.         while (rexxMsg = (struct RexxMsg *)GetMsg(port)) {
  1248.  
  1249.             if (rexxMsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG) {
  1250.  
  1251.                 FreeRexxCommand(rexxMsg);
  1252.  
  1253.                 missing--;
  1254.             }
  1255.             else {
  1256.  
  1257.                 rexxMsg->rm_Result1 = RC_FATAL;
  1258.  
  1259.                 ReplyMsg((struct Message *)rexxMsg);
  1260.             }
  1261.         }
  1262.     }
  1263.  
  1264.     DeleteMsgPort(port);
  1265.  
  1266.     Permit();
  1267. }
  1268.  
  1269. /* ------------------------------- FreeRexxCommand ----------------------------
  1270.  
  1271.  Free memory/file handles related to message <rexxmessage> replied by the
  1272.  ARexx server.
  1273.  
  1274. */
  1275.  
  1276. void
  1277. FreeRexxCommand(rexxMsg)
  1278.  
  1279. struct RexxMsg *rexxMsg;
  1280. {
  1281.     if (rexxMsg->rm_Result1 == RC_OK) 
  1282.         if (rexxMsg->rm_Result2)
  1283.             DeleteArgstring((char *)rexxMsg->rm_Result2);
  1284.  
  1285.     if (rexxMsg->rm_Stdin)
  1286.         Close(rexxMsg->rm_Stdin);
  1287.  
  1288.     if (rexxMsg->rm_Stdout && (rexxMsg->rm_Stdout != rexxMsg->rm_Stdin))
  1289.         Close(rexxMsg->rm_Stdout);
  1290.  
  1291.     DeleteArgstring((char *)ARG0(rexxMsg));
  1292.  
  1293.     DeleteRexxMsg(rexxMsg);
  1294. }
  1295.  
  1296. ///
  1297. /// "execute programs"
  1298.  
  1299. /* -------------------------------- DoExecute ------------------------------------
  1300.  
  1301.  Execute a DOS command.
  1302.  
  1303. */
  1304.  
  1305. void
  1306. DoExecute(cmd, async, output, directory, stack, prio)
  1307.  
  1308. UBYTE *cmd, *output, *directory;
  1309. UWORD stack;
  1310. WORD  prio;
  1311. BOOL  async;
  1312. {
  1313.     BPTR newCurrentDir;
  1314.  
  1315.     if (!directory)
  1316.         directory = "progdir:";
  1317.  
  1318.     if (!output)
  1319.         output = "NIL:";
  1320.  
  1321.     if (newCurrentDir = Lock(directory, SHARED_LOCK)) {
  1322.  
  1323.         BPTR inHandle, outHandle, oldCurrentDir = CurrentDir(newCurrentDir);
  1324.  
  1325.         if (outHandle = Open(output, MODE_NEWFILE)) {
  1326.  
  1327.             struct TagItem tagItems[] = {
  1328.  
  1329.                 SYS_Output,      NULL,
  1330.                 SYS_Input ,      NULL,
  1331.                 NP_ConsoleTask,  NULL,
  1332.                 SYS_UserShell,   TRUE,
  1333.                 SYS_Asynch,      async,
  1334.                 NP_StackSize,    stack,
  1335.                 NP_Priority,     prio,
  1336.                 TAG_DONE 
  1337.             };
  1338.  
  1339.             struct MsgPort *oldct, *newct;
  1340.  
  1341.             BOOL success = FALSE;
  1342.  
  1343.             if (IsInteractive(outHandle)) {
  1344.  
  1345.                 newct = ((struct FileHandle *)BADDR(outHandle))->fh_Type;
  1346.                 oldct = SetConsoleTask(newct);
  1347.  
  1348.                 inHandle = Open("CONSOLE:", MODE_OLDFILE);
  1349.  
  1350.                 SetConsoleTask(oldct);
  1351.             }
  1352.             else {
  1353.  
  1354.                 inHandle = Open("NIL:", MODE_OLDFILE);
  1355.                 newct    = NULL;
  1356.             }
  1357.  
  1358.             if (inHandle) {
  1359.  
  1360.                 tagItems[0].ti_Data = outHandle;
  1361.                 tagItems[1].ti_Data = inHandle;
  1362.                 tagItems[2].ti_Data = newct;
  1363.  
  1364.                 if (SystemTagList(cmd, tagItems) != -1L)
  1365.                     success = TRUE;
  1366.  
  1367.                 if (!(async && success))
  1368.                     Close(inHandle);
  1369.             }
  1370.  
  1371.             if (!(async && success))
  1372.                 Close(outHandle);
  1373.         }
  1374.  
  1375.         CurrentDir(oldCurrentDir);
  1376.  
  1377.         UnLock(newCurrentDir);
  1378.     }
  1379. }
  1380.  
  1381. ///
  1382. /// "Server"
  1383.  
  1384. /* -------------------------------- ARexxServer --------------------------------
  1385.  
  1386.  ARexx server; used to process  ARexx  commands  sent  by  ToolManager.  This
  1387.  function  is  installed  as  background  task.  Run until a SIG_HANDSHAKE is
  1388.  recieved from the  main  task.  Rise  SIG_HANDSHAKE  on  exit  (multitasking
  1389.  disabled,  i.e.  if  the  main  task  detects  the signal, this task is gone
  1390.  already).
  1391.  
  1392. */
  1393.  
  1394. __geta4 void
  1395. ARexxServer()
  1396. {
  1397.     struct MsgPort *port;
  1398.  
  1399.     Forbid();
  1400.  
  1401.     if (port = CreateMsgPort()) {
  1402.  
  1403.         ULONG mask;
  1404.         UWORD missing = 0;
  1405.  
  1406.         port->mp_Node.ln_Name = "DOCKSERVER";
  1407.  
  1408.         AddPort(port);
  1409.  
  1410.         do {
  1411.  
  1412.             struct RexxMsg *rexxMsg;
  1413.  
  1414.             mask = Wait(1L<<(port->mp_SigBit) | SIG_KILL);
  1415.  
  1416.             while (rexxMsg = (struct RexxMsg *)GetMsg(port)) {
  1417.  
  1418.                 if (rexxMsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG) {
  1419.  
  1420.                     FreeRexxCommand(rexxMsg);
  1421.  
  1422.                     if (missing)
  1423.                         missing--;
  1424.                 }
  1425.                 else {
  1426.  
  1427.                     struct Event *event;
  1428.  
  1429.                     if (event = (struct Event *)SearchName(&EventList, ARG0(rexxMsg))) {
  1430.  
  1431.                         if (event->Command) {
  1432.  
  1433.                             static UBYTE buffer[1024];
  1434.  
  1435.                             strcpy(buffer, event->Command);
  1436.  
  1437.                             Replace(buffer, "%SCREEN", Screen);
  1438.                             Replace(buffer, "%GOLDED", Host  );
  1439.  
  1440.                             if (event->Activate)
  1441.                                 SendRexxCommand(Host, "WINDOW FORCE", port, TRUE, &missing, NULL);
  1442.  
  1443.                             switch (event->Type) {
  1444.  
  1445.                                 case TMET_ARexx:
  1446.  
  1447.                                     SendRexxCommand("AREXX", buffer, port, TRUE, &missing, NULL);
  1448.                                     break;
  1449.  
  1450.                                 case TMET_GoldED:
  1451.  
  1452.                                     SendRexxCommand(Host, buffer, port, TRUE, &missing, NULL);
  1453.                                     break;
  1454.  
  1455.                                 case TMET_CLI:
  1456.                                 case TMET_WB:
  1457.  
  1458.                                     DoExecute(buffer, TRUE, event->Output, event->Dir, 8192, 0);
  1459.                                     break;
  1460.  
  1461.                                 case TMET_Hotkey:
  1462.  
  1463.                                     InsertEvent(buffer);
  1464.                                     break;
  1465.                             }
  1466.                         }
  1467.                     }
  1468.  
  1469.                     rexxMsg->rm_Result1 = NULL;
  1470.                     rexxMsg->rm_Result2 = NULL;
  1471.  
  1472.                     ReplyMsg((struct Message *)rexxMsg);
  1473.                 }
  1474.             }
  1475.  
  1476.         } while (!(mask & SIG_KILL));
  1477.  
  1478.         CloseRexxPort(port, missing, TRUE);
  1479.     }
  1480.     else
  1481.         Wait(SIG_KILL);
  1482.  
  1483.     Forbid();
  1484.  
  1485.     Signal(MainTask, SIG_HANDSHAKE);
  1486. }
  1487.  
  1488. ///
  1489.